using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml;
using System.Diagnostics;

namespace PocketSettings
{
    public class PocketSettings
    {
        #region fields
        private static bool bsingleton = false;
        private static PocketSettings _singleton;
        CommonSettings _common = new CommonSettings();
        Profile _profile = null;
        string _settingsFileLocation = "";
        

        #endregion


        #region properties
        private List<Profile> _profiles = new List<Profile>();

        public List<Profile> Profiles
        {
            get { return _profiles; }
        }

        public CommonSettings Common
        {
            get
            { return _common; }
        }

        public Profile SelectedUserProfile
        {
            get { return _profile; }
        }
        #endregion


        private PocketSettings()
        {
        }

        public static PocketSettings Create()
        {
            Debug.WriteLine("PocketSettings created");
            if (!bsingleton)
            {
                _singleton = new PocketSettings();
                bsingleton = true;
                return _singleton;
            }
            else
                return _singleton;
        }


        public static PocketSettings Create(string filename)
        {
            Debug.WriteLine("PocketSettings created");
            if (!bsingleton)
            {
                _singleton = new PocketSettings();
                bsingleton = true;
                _singleton.FromDisk(filename);
                _singleton._settingsFileLocation = filename;
                _singleton.LoadUserProfile(_singleton.Common.SelectedProfile);
                return _singleton;
            }
            else
                return _singleton;
        }
        
        public void LoadUserProfile(string userprofilename)
        {
            if (userprofilename == "")
            {
                this._profile = new Profile("default");
                _profiles.Add(_profile);
                this.Common.SelectedProfile = _profile.Name;
                //this.ToDisk(_settingsFileLocation);
            }
            else
            {
                bool found = false;
                for (int i = 0; i < this.Profiles.Count; i++)
                {
                    if (this.Profiles[i].Name == userprofilename)
                    {
                        // this is the profile wich we were looking for
                        this._profile = this.Profiles[i];
                        this.Common.SelectedProfile = _profile.Name;
                        found = true;
                        break;
                    }
                }
                if (!found)
                {
                    // profile not found, create new profile
                    this._profile = new Profile(userprofilename);
                    _profiles.Add(_profile);
                    this.Common.SelectedProfile = _profile.Name;
                }
            }
        }

        public void ToDisk(string filename)
        {
            if (filename != "" && filename != null)
            {
                Debug.WriteLine("PocketSettings wrote to disk");

                customSerialize(filename);
            }
            else
                throw new Exception("Setting filename not set");
        }

        public void ToDisk()
        {
            ToDisk(this._settingsFileLocation);
        }

        public void FromDisk(string filename)
        {
            if (filename != "" && filename != null)
            {
                Debug.WriteLine("PocketSettings load from disk");

                //this._common = new CommonSettings();
                //this._profiles.Clear();
                _settingsFileLocation = filename;
                FileInfo fi = new FileInfo(filename);


                if (fi.Exists && fi.Length > 0)
                    customDeSerialize(filename);
            }
            else
                throw new Exception("Setting filename not set");
        }

        public void FromDisk()
        {
            FromDisk(_settingsFileLocation);
        }

        private void customSerialize(string filename)
        {
            using (FileStream fs = new FileStream(filename, FileMode.Create))
            {
                //XmlWriter writer = XmlWriter.Create(fs);
                //writer.WriteStartDocument();
                //// TODO: loop dictionary
                //writer.WriteComment("MilkAndSugar");
                //writer.WriteStartElement("MilkAndSugar");
                //foreach (KeyValuePair<string, string> pair in SettingDictionary)
                //{

                //    writer.WriteElementString(pair.Key, pair.Value);
                //}
                //writer.WriteEndElement();

                //writer.WriteEndDocument();
                StringBuilder sb = new StringBuilder();
                sb.Append("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
                sb.Append("<MilkAndSugar>");

                sb.Append("<common>");
                foreach (KeyValuePair<string, string> kvp in Common.Settings.SettingDictionary)
                {
                    sb.Append(string.Format("<{0}><![CDATA[{1}]]></{0}>", kvp.Key, kvp.Value));
                }

                sb.Append("</common>");

                sb.Append("<profiles>");

                foreach (Profile userProfile in Profiles)
                {
                    sb.Append(string.Format("<{0}>", userProfile.Name));
                    foreach (KeyValuePair<string, string> kvp in userProfile.Settings.SettingDictionary)
                    {
                        sb.Append(string.Format("<{0}><![CDATA[{1}]]></{0}>", kvp.Key, kvp.Value));
                    }
                    sb.Append(string.Format("</{0}>", userProfile.Name));
                }

                sb.Append("</profiles>");

                //foreach (KeyValuePair<string, string> pair in SettingDictionary)
                //{
                //    sb.Append(string.Format("<{0}><![CDATA[{1}]]></{0}>", pair.Key, pair.Value));
                //}
                sb.Append("</MilkAndSugar>");
                Debug.WriteLine(sb.ToString(), "settings xml");
                XmlDocument setdoc = new XmlDocument();
                setdoc.LoadXml(sb.ToString());
                setdoc.Save(fs);
            }
        }

        private void customDeSerialize(string filename)
        {
            try
            {
                using (FileStream fs = new FileStream(filename, FileMode.Open))
                {
                    XmlDocument document = new XmlDocument();
                    document.Load(fs);

                    // load common settings
                    Debug.WriteLine("loading common settings");

                    XmlNodeList commonNodes = document.SelectNodes("descendant::MilkAndSugar/common/*");
                    if (_common == null)
                        _common = new CommonSettings();

                    foreach (XmlNode commonNode in commonNodes)
                    {
                        _common.Settings.Add(
                            commonNode.Name,
                            commonNode.InnerText);
                    }


                    //XmlNodeList nodes = document.ChildNodes[1].ChildNodes;

                    // load profile settings
                    Debug.WriteLine("loading profiles");
                    XmlNodeList profileNodes = document.SelectNodes("descendant::MilkAndSugar/profiles/*");
                    foreach (XmlNode profileNode in profileNodes)
                    {
                        Debug.WriteLine("loading profile settings");

                        Profile xprofile = new Profile(profileNode.Name);
                        foreach (XmlNode settingNode in profileNode.ChildNodes)
                        {
                            xprofile.Settings.Add(
                                settingNode.Name,
                                settingNode.InnerText);
                        }

                        _profiles.Add(xprofile);
                        //for (int i = 0; i < profileNodes.Count; i++)
                        //{

                        //    //name = profileNodes[i].Name;
                        //    //value = profileNodes[i].InnerText;
                        //    //_profile.Settings.SettingDictionary.Add(name, value);
                        //}
                    }

                }
            }
            catch (FileNotFoundException)
            {
            }
        }


    }
}
